package com.openharmony.filepicker.adapter;

import com.openharmony.filepicker.ResourceTable;
import com.openharmony.filepicker.bean.FileItemBeanImpl;
import com.openharmony.filepicker.config.FilePickerManager;
import com.openharmony.filepicker.engine.ImageLoadController;
import com.openharmony.filepicker.filetype.RasterImageFileType;
import com.openharmony.filepicker.filetype.VideoFileType;
import ohos.agp.components.Component;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.ListContainer;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.Text;
import ohos.agp.components.Image;
import ohos.agp.components.Checkbox;
import ohos.agp.components.RadioButton;
import ohos.agp.components.element.PixelMapElement;
import ohos.app.Context;
import ohos.global.resource.NotExistException;
import ohos.global.resource.ResourceManager;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class FileListAdapter extends BaseAdapter {

    public static final int DEFAULT_FILE_TYPE = 10001;

    private Context mContext;
    private boolean isSingleChoice;
    private ArrayList<FileItemBeanImpl> dataList = new ArrayList<>(10);
    private int latestChoicePos = -1;
    private ListContainer listContainer;

    public FileListAdapter(Context context, boolean isSingleChoice) {
        this.mContext = context;
        this.isSingleChoice = isSingleChoice;
    }

    public FileListAdapter(Context context) {
        this.mContext = context;
        this.isSingleChoice = FilePickerManager.INSTANCE().getConfig().isSingleChoice();
    }

    @Override
    public int getCount() {
        return dataList.size();
    }

    @Override
    public FileItemBeanImpl getItem(int position) {
        if (position >= 0
                && position < dataList.size()) {
            return dataList.get(position);
        }
        return null;
    }

    @Override
    public Component onCreateViewHolder(ComponentContainer parent, int viewType) {
        if (parent instanceof ListContainer) {
            listContainer = (ListContainer) parent;
        }

        if (isSingleChoice) {
            Component component = LayoutScatter.getInstance(mContext).parse(ResourceTable.Layout_item_single_choise_list_file_picker, null, false);
            component.setTag(new FileListItemSingleChoiceHolder(component));
            return component;
        } else {
            Component component = LayoutScatter.getInstance(mContext).parse(ResourceTable.Layout_item_list_file_picker, null, false);
            component.setTag(new FileListItemHolder(component));
            return component;
        }

    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public Component getComponent(int i,
                                  Component component,
                                  ComponentContainer componentContainer) {
        final Component cpt;
        if (component == null) {
            cpt = onCreateViewHolder(componentContainer, 0);
        } else {
            cpt = component;
        }
        BaseViewHolder viewHolder = (BaseViewHolder) cpt.getTag();
        viewHolder.bind(dataList.get(i), i);
        return cpt;
    }

    public boolean isSingleChoice() {
        return isSingleChoice;
    }

    public void setSingleChoice(boolean singleChoice) {
        isSingleChoice = singleChoice;
    }

    public ArrayList<FileItemBeanImpl> getDataList() {
        return dataList;
    }

    public void setDataList(ArrayList<FileItemBeanImpl> dataList) {
        this.dataList = dataList;
    }

    /*--------------------------OutSide call method begin------------------------------*/

    public interface CanSelect {
        boolean isCanSelect();
    }

    public interface CheckFailedFunc {
        void checkFailedFunc();
    }

    public void setNewData(List<FileItemBeanImpl> list) {
        if (list != null) {
            dataList.clear();
            dataList.addAll(list);
            notifyDataChanged();
        }
    }

    public void multipleCheckOrNo(
            FileItemBeanImpl item,
            int position,
            CanSelect canSelect,
            CheckFailedFunc checkFailedFunc
    ) {
        if (item.isChecked()) {
            // 当前被选中，说明即将取消选中
            // had selected, will dis-select
            multipleDisCheck(position);
        } else if (canSelect.isCanSelect()) {
            // 当前未被选中，并且检查合格，则即将新增选中
            // current item is not selected, and can be selected, will select
            multipleCheck(position);
        } else {
            // 新增选中项失败的情况
            // add new selected item failed
            checkFailedFunc.checkFailedFunc();
        }
    }

    public void multipleCheck(int position) {
        FileItemBeanImpl item = getItem(position);
        if (item != null) {
            System.out.println("===multipleCheck===>" + position);
            item.setChecked(true);
            notifyDataSetItemChanged(position);
        }
    }

    public void multipleDisCheck(int position) {
        FileItemBeanImpl item = getItem(position);
        if (item != null) {
            item.setChecked(false);
            System.out.println("===multipleDisCheck===>");
            notifyDataSetItemChanged(position);
        }
    }

    public void singleCheck(int position) {

        System.out.println("=== single check latestChoicePos : " + latestChoicePos);

        if (latestChoicePos == -1) {

            // 从未选中过
            FileItemBeanImpl item = getItem(position);
            if (item != null) {
                item.setChecked(true);
//                notifyDataSetItemChanged(position);
                notifyDataChanged();
            }
            latestChoicePos = position;

        } else if (latestChoicePos == position) {
            FileItemBeanImpl item = getItem(latestChoicePos);
            if (item != null) {
                item.setChecked(false);
//                notifyDataSetItemChanged(latestChoicePos);
                notifyDataChanged();
            }
            latestChoicePos = -1;
        } else {
            FileItemBeanImpl item = getItem(latestChoicePos);
            if (item != null) {
                item.setChecked(false);
//                notifyDataSetItemChanged(latestChoicePos);
                notifyDataChanged();
            }
            latestChoicePos = position;
            FileItemBeanImpl bean = getItem(latestChoicePos);
            if (bean != null) {
                bean.setChecked(true);
//                notifyDataSetItemChanged(latestChoicePos);
                notifyDataChanged();
            }
        }
    }

    public void disCheckAll() {
        for (int i = 0; i < dataList.size(); i++) {
            FileItemBeanImpl bean = dataList.get(i);
            if (!(FilePickerManager.INSTANCE().getConfig().isSkipDir() && bean.isDir()) && bean.isChecked()) {
                bean.setChecked(false);
            }
        }
        notifyDataChanged();
    }

    public void checkAll(int hadSelectedCount) {
        int checkCount = hadSelectedCount;
        for (int i = 0; i < dataList.size(); i++) {
            FileItemBeanImpl item = dataList.get(i);
            if (checkCount >= FilePickerManager.INSTANCE().getConfig().getMaxSelectable()) {
                return;
            }
            if (!(FilePickerManager.INSTANCE()
                    .getConfig().isSkipDir()
                    && item.isDir()) && !item.isChecked()) {
                item.setChecked(true);
                checkCount++;
                notifyDataChanged();
            }
        }
    }

    /*--------------------------OutSide call method end------------------------------*/

    /*--------------------------ViewHolder Begin------------------------------*/

    public class FileListItemSingleChoiceHolder extends BaseViewHolder {

        private boolean isSkipDir = FilePickerManager.INSTANCE().getConfig().isSkipDir();
        private Text mTvFileName;
        private RadioButton mRbItem;
        private Image mIcon;
        private FileItemBeanImpl mItemBeanImpl;
        private int mPosition;
        private PixelMapElement checked;
        private PixelMapElement unChecked;

        public FileListItemSingleChoiceHolder(Component itemView) {
            super(itemView);
            mTvFileName = (Text) itemView.findComponentById(ResourceTable.Id_tv_list_file_picker);
            mRbItem = (RadioButton) itemView.findComponentById(ResourceTable.Id_rb_list_file_picker);
            mIcon = (Image) itemView.findComponentById(ResourceTable.Id_iv_icon_list_file_picker);

            initElement();
        }

        private void initElement() {
            ResourceManager resourceManager = mContext.getResourceManager();
            try {
                checked = new PixelMapElement(resourceManager.getResource(ResourceTable.Media_ic_radio_check_on));
                unChecked = new PixelMapElement(resourceManager.getResource(ResourceTable.Media_ic_radio_check_off));
            } catch (IOException | NotExistException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void bind(FileItemBeanImpl itemImpl, int position) {
            mItemBeanImpl = itemImpl;
            mPosition = position;

            mTvFileName.setText(itemImpl.getFileName());
            mRbItem.setChecked(itemImpl.isChecked());
            mRbItem.setVisibility(Component.VISIBLE);
            mRbItem.setBackground(itemImpl.isChecked() ? checked : unChecked);

            boolean isDir = new File(itemImpl.getFilePath()).isDirectory();

            mRbItem.setClickedListener(new Component.ClickedListener() {
                @Override
                public void onClick(Component component) {
                    if (listener != null) {
                        listener.onItemChildrenClick(component, position);
                    }
                }
            });

            if (isDir) {
                mIcon.setPixelMap(ResourceTable.Media_ic_folder_file_picker);
                mRbItem.setVisibility(isSkipDir ? Component.HIDE : Component.VISIBLE);
                return;
            }

            int resId = ResourceTable.Media_ic_unknown_file_picker;
            if (itemImpl.getFileType() != null) {
                resId = itemImpl.getFileType().getFileIconResId();
            }
            if (itemImpl.getFileType() instanceof RasterImageFileType || itemImpl.getFileType() instanceof VideoFileType) {
                ImageLoadController.INSTANCE().load(
                        mContext,
                        mIcon,
                        itemImpl.getFilePath(),
                        resId
                );
            } else {
                mIcon.setPixelMap(resId);
            }

        }
    }

    public class FileListItemHolder extends BaseViewHolder {

        private boolean isSkipDir = FilePickerManager.INSTANCE().getConfig().isSkipDir();
        private Text mTvFileName;
        private Checkbox mCbItem;
        private Image mIcon;
        private FileItemBeanImpl mItemBeanImpl;
        private int mPosition;
        private PixelMapElement checked;
        private PixelMapElement unChecked;

        public FileListItemHolder(Component itemView) {
            super(itemView);
            mTvFileName = (Text) itemView.findComponentById(ResourceTable.Id_tv_list_file_picker);
            mCbItem = (Checkbox) itemView.findComponentById(ResourceTable.Id_cb_list_file_picker);
            mIcon = (Image) itemView.findComponentById(ResourceTable.Id_iv_icon_list_file_picker);
            initElement();
        }

        private void initElement() {
            ResourceManager resourceManager = mContext.getResourceManager();
            try {
                checked = new PixelMapElement(resourceManager.getResource(ResourceTable.Media_checkbox_selected));
                unChecked = new PixelMapElement(resourceManager.getResource(ResourceTable.Media_checkbox_unselected));
            } catch (IOException | NotExistException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void bind(FileItemBeanImpl itemImpl, int position) {
            mItemBeanImpl = itemImpl;
            mPosition = position;
            mTvFileName.setText(itemImpl.getFileName());
            mCbItem.setChecked(itemImpl.isChecked());
            mCbItem.setBackground(itemImpl.isChecked() ? checked : unChecked);
            mCbItem.setVisibility(Component.VISIBLE);
            System.out.println("===bind===>" + position + "setChecked:" + mCbItem.isChecked());
            mCbItem.setClickedListener(new Component.ClickedListener() {
                @Override
                public void onClick(Component component) {
                    if (listener != null) {
                        listener.onItemChildrenClick(component, position);
                    }
                }
            });

            boolean isDir = new File(itemImpl.getFilePath()).isDirectory();
            if (isDir) {
                mIcon.setPixelMap(ResourceTable.Media_ic_folder_file_picker);
                mCbItem.setVisibility(isSkipDir ? Component.HIDE : Component.VISIBLE);
                return;
            }

            int resId = ResourceTable.Media_ic_unknown_file_picker;
            if (itemImpl.getFileType() != null) {
                resId = itemImpl.getFileType().getFileIconResId();
            }
            if (itemImpl.getFileType() instanceof RasterImageFileType || itemImpl.getFileType() instanceof VideoFileType) {
                ImageLoadController.INSTANCE().load(
                        mContext,
                        mIcon,
                        itemImpl.getFilePath(),
                        resId
                );
            } else {
                mIcon.setPixelMap(resId);
            }
        }
    }

    public static abstract class BaseViewHolder extends ViewHolder {
        public BaseViewHolder(Component itemView) {

        }

        public abstract void bind(FileItemBeanImpl itemImpl, int position);
    }

    /*--------------------------ViewHolder End------------------------------*/

    private ItemChildrenClickListener listener;

    public void setItemChildrenClickListener(ItemChildrenClickListener listener) {
        this.listener = listener;
    }

    public interface ItemChildrenClickListener {
        void onItemChildrenClick(Component component, int position);
    }
}
